home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 9068 < prev    next >
Encoding:
Text File  |  1996-08-05  |  6.5 KB  |  150 lines

  1. Newsgroups: comp.lang.c++
  2. Path: BALROG.NCI.NIH.GOV!SYSTEX
  3. From: systex@BALROG.NCI.NIH.GOV (Donald G. Plugge, Systex Inc., (301)210-7701)
  4. Subject: VMS Descriptor Class
  5. Message-ID: <1996Feb27.170009.15649@alw.nih.gov>
  6. Sender: postman@alw.nih.gov (AMDS Postmaster)
  7. Nntp-Posting-Host: balrog.nci.nih.gov
  8. Reply-To: systex@BALROG.NCI.NIH.GOV
  9. Organization: Organization, City, State, etc.
  10. Date: Tue, 27 Feb 1996 17:00:09 GMT
  11.  
  12. > In the spirit of object oriented programming, I'd like to ask a design question
  13. > in order to determine which C++ component to utilize in a particular case.  I
  14. > have experience with C, however, I have just begun to explore the vast
  15. > assortment of features available in C++.  My questions concerns the string
  16. > class and whether to include, cast or inherit them into another structure.
  17. > My coding is done on an Alpha 3400 running VMS 6.1 with DEC C++ version 3.1.
  18. > In the VMS environment system service calls use a structure called a descriptor
  19. > to pass character data.  The definition of the structure is contained in the
  20. > <descrip.h> file.  The relevant section follows below.  Notice that the code
  21. > #defines a $DESCRIPTOR macro to place an array of characters into the
  22. > descriptor structure.  The new descriptor is then ready to be passed to the
  23. > system service.
  24. > /*
  25. >  *      Fixed-Length Descriptor:
  26. >  */
  27. > struct  dsc$descriptor_s
  28. > {
  29. >         unsigned short  dsc$w_length;   /* length of data item in bytes,
  30. >                                              or if dsc$b_dtype is DSC$K_DTYPE_V, bits,
  31. >                                              or if dsc$b_dtype is DSC$K_DTYPE_P, digits (4 bits each) */
  32. >         unsigned char   dsc$b_dtype;    /* data type code */
  33. >         unsigned char   dsc$b_class;    /* descriptor class code = DSC$K_CLASS_S */
  34. >         char            *dsc$a_pointer; /* address of first byte of data storage */
  35. > };
  36. > /*
  37. >  *      A simple macro to construct a string descriptor:
  38. >  */
  39. > #define $DESCRIPTOR(name,string)        struct dsc$descriptor_s name = { sizeof(string)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
  40. > An example of a call to the macro would be:
  41. >     dsc$descriptor_s dsc;
  42. >     $DESCRIPTOR(dsc, "XYZ");
  43. >     status = SYS$GETDVI (0, 0, &dsc, &itmlst[0], &iosb, 0, 0, 0);
  44. > The $DESCRIPTOR syntax only takes literal character array and not a Class
  45. > strings.  If I create a subroutine to call the system service by passing a
  46. > literal character array, that works fine.  However, if I pass a string object,
  47. > then the $DESCRIPTOR fails.
  48. > Would it be wise to create a descriptor class which is derived from a string
  49. > class?  From what I've been reading in "Effective C++" by Meyers the derived
  50. > class "isa" base class.  So, the derived descriptor should really be a string,
  51. > but that doesn't seem to fit.  Perhaps the descriptor class should contain a
  52. > member function which returns the proper descriptor.  Or perhaps I shouldn't
  53. > use the DEC provided descrip.h at all and create a new structure based upon
  54. > the string class.
  55. > Any thoughts about what is good and proper?
  56. >                                         Donald G. Plugge
  57. > ac@n
  58.  
  59. Really, the best thing to do (IMHO) is to hide the dsc$descriptor_s class (a 
  60. struct is a class) in a class as an "attribute" (data member) of another 
  61. class.  This way you (the author of the class) have complete control over the 
  62. interface and implementation of the class.  You could actually store a 
  63. pointer to the descriptor if you wanted better implementation hiding (that 
  64. way, the user of the class doesn't even have to know descriptors even exist).
  65.  
  66. I say this from some experience. I am currently working on OpenVMS also 
  67. (currently VAX, but expect to move to Alpha soon).  I have tried several 
  68. designs.  The first was so awful, I'm embarrassed to admit it: I used 
  69. multiple inheritance deriving from String _and_ dsc$descriptor - yuk!  I also 
  70. tried inheriting privately from dsc$descriptor_s.  This was also a bad 
  71. design, but it took longer to see why.
  72.  
  73. Also, In this case I think a type cast to dsc$descriptor& is appropriate 
  74. here:
  75.  
  76. class FixedStringDescriptor
  77. {
  78.     //  Attribute:
  79.  
  80.     dsc$descriptor_s Descriptor;
  81. public:
  82.  
  83.     //  Initialization:
  84.  
  85.     FixedStringDescriptor() {/*...*/}
  86.  
  87.     //...
  88.  
  89.     //  Operations:
  90.  
  91.     operator const dsc$descriptor_s&() {return Descriptor;}
  92.  
  93.     //...
  94. };
  95.  
  96. so that you can pass a FixedStringDescriptor object directly to a system 
  97. service call with the argument coded as "const dsc$descriptor&" (I write my 
  98. own prototypes for VMS system service calls.  The ones DEC provides use "..." 
  99. so are not type-safe).  Some OO experts dislike user-defined type casts, but 
  100. I this one seems justified.
  101.  
  102. Note that casting to _const_ dsc$descriptor_s& is not as restrictive as it 
  103. might seem at first.  The users can still modify the data pointed to by 
  104. dsc$a_pointer, they just cannot modify the pointer itself (nor any other 
  105. dsc$descriptor_s members).
  106.  
  107. I currently have an implemenation of FixedStringDescriptor that solves what 
  108. you are trying to do that I can send you if you are interested.  It is 
  109. patterned after the STL (Standard Template Library) vector class.  
  110. Interfacing with the String class is indirect, but fairly straight forward. 
  111. We have a string class that we use after bad experiences with the DEC String 
  112. class (e.g., my version corrupts the heap if you read from an istream to and 
  113. emtpy String).  So, I provide constructors from const char* rather than 
  114. providing a constructor form (possibly more than one) string classes. Of 
  115. course, allocation is handled "automatically" (as Alexander Stepanov, the 
  116. author of the STL likes to say).  For whatever reason, I decided to implement 
  117. the entire class inline, so the aforementioned implementation hiding is not 
  118. done.
  119.  
  120. To answer the broader question, I think what all of this has taught me about 
  121. OO design, is that sometimes you have to think about things a little deeper. 
  122. It is indeed tempting to think of a descriptor-ized string as a type of 
  123. string, but actually the two are quite different.  A C++ string class is 
  124. dynamic, whereas, a fixed-string descriptor is really just a fixed-length 
  125. buffer.  Also, I think deriving from a general purpose "utility" class (one 
  126. that is not primarily intended for derivation) is usually not a good idea.  
  127. There are no virtual functions to override, so there's little to be gained.  
  128. Reading "Thinking in C++" by Bruce Eckel helped me to see the problem with 
  129. private inheritance.  He says the desire to do this ususally indicates an 
  130. implementation that should be hidden.
  131.  
  132. Hope this helps.
  133.  
  134. Bruce Visscher
  135.  
  136.